from datetime import datetime
from io import BytesIO
from typing import List

from flask import Blueprint, request, jsonify, send_file
from openpyxl.styles import Font, Alignment
from openpyxl.utils import get_column_letter
from openpyxl.workbook import Workbook

from app.db.crud.teacher_management_query import CourseQuery, classes_query
from app.db.model import TeachingScheduleCourse
from app.decorators import require_params
from app.utils.exceptions import MissingParamError, InvalidRoleValueError, InternalServerError, ResourceNotFoundError
from app.utils.str_util import week_field, symbol_info

classes = Blueprint('classes', __name__, url_prefix='/classes')


@classes.route('/info/teaching/schedule/add', methods=["POST"])
# @login_required
# @role_required('all_teacher')
@require_params("role", "semester", "campus", "grade", "class_name", "major", "enrollment_method")
def add_teaching_schedule_course():
    try:
        if hasattr(request, 'validated_params'):
            params: dict = request.validated_params
            request_data = request.form.to_dict() or {}
        else:
            raise MissingParamError("vp")
        role = params.get("role")
        if role not in ["admin"]:
            raise InvalidRoleValueError({"u-facingMsg": "角色异常！"})
        semester = params.get("semester")
        campus = params.get("campus", "")
        grade = params.get("grade", "")
        class_name = params.get("class_name", "")
        major = params.get("major", "")
        enrollment_method = params.get("enrollment_method", "")
        week01 = request_data.get("week01", "")
        week02 = request_data.get("week02", "")
        week03 = request_data.get("week03", "")
        week04 = request_data.get("week04", "")
        week05 = request_data.get("week05", "")
        week06 = request_data.get("week06", "")
        week07 = request_data.get("week07", "")
        week08 = request_data.get("week08", "")
        week09 = request_data.get("week09", "")
        week10 = request_data.get("week10", "")
        week11 = request_data.get("week11", "")
        week12 = request_data.get("week12", "")
        week13 = request_data.get("week13", "")
        week14 = request_data.get("week14", "")
        week15 = request_data.get("week15", "")
        week16 = request_data.get("week16", "")
        week17 = request_data.get("week17", "")
        week18 = request_data.get("week18", "")
        week19 = request_data.get("week19", "")
        week20 = request_data.get("week20", "")
        week21 = request_data.get("week21", "")
        week22 = request_data.get("week22", "")
        max_id1 = classes_query.get_teaching_schedule_max_id1(semester)
        max_id = classes_query.get_teaching_schedule_max_id()
        teaching_schedule_course = TeachingScheduleCourse(
            id=max_id,  # 假设需要递增ID
            semester=semester,
            campus=campus,
            id1=max_id1,  # 假设需要递增ID1
            grade=grade,
            class_name=class_name,
            major=major,
            enrollment_method=enrollment_method,
            week01=week01,
            week02=week02,
            week03=week03,
            week04=week04,
            week05=week05,
            week06=week06,
            week07=week07,
            week08=week08,
            week09=week09,
            week10=week10,
            week11=week11,
            week12=week12,
            week13=week13,
            week14=week14,
            week15=week15,
            week16=week16,
            week17=week17,
            week18=week18,
            week19=week19,
            week20=week20,
            week21=week21,
            week22=week22
        )
        classes_query.add_teaching_schedule(teaching_schedule_course)
        return jsonify({
            "code": 200,
            "message": "success",
            "data": "添加教学进程数据成功"
        })
    except Exception as e:
        user_facing_msg = (
            e.details.get('u-facingMsg')
            if hasattr(e, 'details') and isinstance(e.details, dict) and e.details.get('u-facingMsg', None)
            else "服务器错误"
        )
        raise InternalServerError({"u-facingMsg": user_facing_msg}) from e


@classes.route('/info/teaching/schedule/update', methods=["PUT"])
# @login_required
# @role_required('all_teacher')
@require_params("role", "id")
def update_teaching_schedule_course():
    try:
        if hasattr(request, 'validated_params'):
            params: dict = request.validated_params
            request_data: dict = request.get_json(silent=True) or {}
        else:
            raise MissingParamError("vp")
        role = params.get("role")
        if role not in ["admin"]:
            raise InvalidRoleValueError({"u-facingMsg": "角色异常！"})
        id = int(params.get('id'))
        semester = request_data.get("semester", "")
        campus = request_data.get("campus", "")
        grade = request_data.get("grade", "")
        class_name = request_data.get("class_name", "")
        major = request_data.get("major", "")
        enrollment_method = request_data.get("enrollment_method", "")
        week01 = request_data.get("week01", "")
        week02 = request_data.get("week02", "")
        week03 = request_data.get("week03", "")
        week04 = request_data.get("week04", "")
        week05 = request_data.get("week05", "")
        week06 = request_data.get("week06", "")
        week07 = request_data.get("week07", "")
        week08 = request_data.get("week08", "")
        week09 = request_data.get("week09", "")
        week10 = request_data.get("week10", "")
        week11 = request_data.get("week11", "")
        week12 = request_data.get("week12", "")
        week13 = request_data.get("week13", "")
        week14 = request_data.get("week14", "")
        week15 = request_data.get("week15", "")
        week16 = request_data.get("week16", "")
        week17 = request_data.get("week17", "")
        week18 = request_data.get("week18", "")
        week19 = request_data.get("week19", "")
        week20 = request_data.get("week20", "")
        week21 = request_data.get("week21", "")
        week22 = request_data.get("week22", "")

        classes_query.update_teaching_schedule(id, semester, campus, grade, class_name, major, enrollment_method,
                                               week01,
                                               week02, week03, week04, week05, week06, week07, week08, week09, week10,
                                               week11, week12, week13, week14, week15, week16, week17, week18, week19,
                                               week20, week21, week22)
        return jsonify({
            "code": 200,
            "message": "success",
            "data": "更新教学进程表数据成功"
        })
    except Exception as e:
        user_facing_msg = (
            e.details.get('u-facingMsg')
            if hasattr(e, 'details') and isinstance(e.details, dict) and e.details.get('u-facingMsg', None)
            else "服务器错误"
        )
        raise InternalServerError({"u-facingMsg": user_facing_msg}) from e


@classes.route('/info/teaching/schedule/delete', methods=["DELETE"])
# @login_required
# @role_required('all_teacher')
@require_params("role", "ids")
def delete_teaching_schedule():
    try:
        if hasattr(request, 'validated_params'):
            params: dict = request.validated_params
        else:
            raise MissingParamError("vp")
        role = params.get("role")
        ids = params.get("ids")
        if role not in ["admin"]:
            raise InvalidRoleValueError({"u-facingMsg": "角色异常！"})
        if not ids:
            raise ResourceNotFoundError(extra_details={"u-facingMsg": "班级信息错误"})
        if ',' in ids:
            course_id: List[int] = [int(id_str.strip()) for id_str in ids.split(',') if id_str]
        else:
            course_id = [int(ids)]
        classes_query.delete_teaching_schedule(course_id)
        return jsonify({
            "code": 200,
            "message": "success",
            "data": "删除教学进程表信息成功"
        })
    except Exception as e:
        user_facing_msg = (
            e.details.get('u-facingMsg')
            if hasattr(e, 'details') and isinstance(e.details, dict) and e.details.get('u-facingMsg', None)
            else "服务器错误"
        )
        raise InternalServerError({"u-facingMsg": user_facing_msg}) from e


@classes.route('/info/teaching/schedule/get', methods=["GET"])
# @login_required
# @role_required('all_teacher')
@require_params()
def get_teaching_schedule_course():
    try:
        if hasattr(request, 'validated_params'):
            params: dict = request.args
        else:
            raise MissingParamError("vp")
        class_id = params.get("id", "")
        semester = params.get("semester", "")
        campus = params.get("campus", "")
        class_id1 = params.get("id1", "")
        grade = params.get("grade", "")
        class_name = params.get("class_name", "")
        major = params.get("major", "")
        enrollment_method = params.get("enrollment_method", "")
        week01 = params.get("week01", "")
        week02 = params.get("week02", "")
        week03 = params.get("week03", "")
        week04 = params.get("week04", "")
        week05 = params.get("week05", "")
        week06 = params.get("week06", "")
        week07 = params.get("week07", "")
        week08 = params.get("week08", "")
        week09 = params.get("week09", "")
        week10 = params.get("week10", "")
        week11 = params.get("week11", "")
        week12 = params.get("week12", "")
        week13 = params.get("week13", "")
        week14 = params.get("week14", "")
        week15 = params.get("week15", "")
        week16 = params.get("week16", "")
        week17 = params.get("week17", "")
        week18 = params.get("week18", "")
        week19 = params.get("week19", "")
        week20 = params.get("week20", "")
        week21 = params.get("week21", "")
        week22 = params.get("week22", "")
        page = int(params.get("page", 1))
        page_size = int(params.get("page_size", 14))
        data, total_count = classes_query.get_teaching_schedule_info(class_id, semester, campus, class_id1, grade,
                                                                     class_name,
                                                                     major, enrollment_method, week01, week02, week03,
                                                                     week04, week05, week06, week07, week08, week09,
                                                                     week10, week11, week12, week13, week14, week15,
                                                                     week16, week17, week18, week19, week20, week21,
                                                                     week22, page, page_size)
        return jsonify({
            "code": 200,
            "message": "success",
            "data": data,
            "length": total_count
        })
    except Exception as e:
        user_facing_msg = (
            e.details.get('u-facingMsg')
            if hasattr(e, 'details') and isinstance(e.details, dict) and e.details.get('u-facingMsg', None)
            else "服务器错误"
        )
        raise InternalServerError({"u-facingMsg": user_facing_msg}) from e


@classes.route('/export/teaching/schedule', methods=["GET"])
# @login_required
# @role_required('all_teacher')
@require_params('semester')
def export_teaching_schedule_course():
    try:
        if hasattr(request, 'validated_params'):
            params: dict = request.validated_params
        else:
            raise MissingParamError("vp")
        semester = params.get("semester")
        wb = Workbook()
        ws = wb.active
        ws.title = f"{semester}-各班教学进程表"
        ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=28)
        title_cell = ws.cell(row=1, column=1)
        ws.row_dimensions[1].height = 30
        title_cell.value = f"{semester}各班教学进程表"
        title_cell.font = Font(name='微软雅黑', size=12, bold=True)
        title_cell.alignment = Alignment(horizontal='center', vertical='center')
        ws.merge_cells(start_row=2, start_column=1, end_row=5, end_column=1)
        ws.merge_cells(start_row=2, start_column=2, end_row=5, end_column=2)
        ws.merge_cells(start_row=2, start_column=3, end_row=5, end_column=3)
        ws.merge_cells(start_row=2, start_column=4, end_row=5, end_column=4)
        ws.merge_cells(start_row=2, start_column=5, end_row=5, end_column=5)
        ws.merge_cells(start_row=2, start_column=6, end_row=5, end_column=6)
        # 这部分写标题
        titles = ["校区", "序号", "年级", "班级", "专业", "升学方式"]
        for col, title in enumerate(titles, 1):
            cell = ws.cell(row=2, column=col)
            cell.value = title
            cell.font = Font(name='微软雅黑', size=9)
            cell.alignment = Alignment(horizontal='center', vertical='center')
        labels = ["月份", "周次", "开始日期", "结束日期"]
        for i, label in enumerate(labels, start=2):
            cell = ws.cell(row=i, column=7, value=label)
            cell.font = Font(name='微软雅黑', size=10)
        ws.column_dimensions['E'].width = 40
        ws.column_dimensions['F'].width = 15
        # 这部分是本学期时间相关的信息
        current_semester_weeks = classes_query.get_current_week(semester)
        current_semester_course, total_count = classes_query.get_teaching_schedule_info('', semester)
        cur_col = 8
        cur_mon_col = 8
        for i in range(1, 23):
            start_str, end_str = current_semester_weeks[week_field(i)].split('-')
            start_day = datetime.strptime(start_str.replace('.', '-'), "%Y-%m-%d").date().day
            end_day = datetime.strptime(end_str.replace('.', '-'), "%Y-%m-%d").date().day
            start_mon = datetime.strptime(start_str.replace('.', '-'), "%Y-%m-%d").date().month
            end_mon = datetime.strptime(end_str.replace('.', '-'), "%Y-%m-%d").date().month
            if start_mon != end_mon:
                ws.merge_cells(start_row=2, start_column=cur_mon_col, end_row=2, end_column=cur_col)
                ws.cell(row=2, column=cur_mon_col, value=f"{start_mon}月")
                cur_mon_col = cur_col + 1

            ws.cell(row=3, column=i + 7, value=i)
            ws.cell(row=4, column=cur_col, value=start_day)
            ws.cell(row=5, column=cur_col, value=end_day)
            cur_col += 1

        # 下面是本学期每个班级的相关信息
        each_row = 6
        cur_col = 8
        for col in range(8, 30):  # 30 是因为 range 不包含 end
            col_letter = get_column_letter(col)
            ws.column_dimensions[col_letter].width = 18
        for each_class_info in current_semester_course:
            ws.cell(row=each_row, column=1, value=each_class_info['campus'])
            ws.cell(row=each_row, column=2, value=each_class_info['id1'])
            ws.cell(row=each_row, column=3, value=each_class_info['grade'])
            ws.cell(row=each_row, column=4, value=each_class_info['class_name'])
            ws.cell(row=each_row, column=5, value=each_class_info['major'])
            ws.cell(row=each_row, column=6, value=each_class_info['enrollment_method'])
            for i in range(0, 22):
                symbol_info(ws, each_row, i + cur_col, each_class_info[week_field(i + 1)])
            ws.row_dimensions[each_row].height = 25
            each_row += 1

        # 设置整体居中和边框
        for row in ws.iter_rows(min_row=1, max_row=ws.max_row, min_col=1, max_col=ws.max_column):
            for cell in row:
                if cell.row == 1 and cell.column == 1:
                    continue  # 跳过A1单元格
                cell.alignment = Alignment(horizontal='center', vertical='center')

        output = BytesIO()
        wb.save(output)
        output.seek(0)
        return send_file(
            output,
            as_attachment=True,
            download_name=f"{semester}各班教学进程表.xlsx"
        )

    except Exception as e:
        user_facing_msg = (
            e.details.get('u-facingMsg')
            if hasattr(e, 'details') and isinstance(e.details, dict) and e.details.get('u-facingMsg', None)
            else "服务器错误"
        )
        raise InternalServerError({"u-facingMsg": user_facing_msg}) from e


@classes.route('/teaching/week', methods=["GET"])
# @login_required
# @role_required('all_teacher')
@require_params('semester')
def get_teaching_schedule_week():
    try:
        if hasattr(request, 'validated_params'):
            params: dict = request.validated_params
        else:
            raise MissingParamError("vp")
        semester = params.get("semester")
        not_handle_data = classes_query.get_current_week(semester)
        data = {
            key[4:]: value
            for key, value in not_handle_data.items()
            if key.startswith("week") and key[4:].isdigit()
        }
        return jsonify({
            "code": 200,
            "message": "success",
            "data": data
        })
    except Exception as e:
        user_facing_msg = (
            e.details.get('u-facingMsg')
            if hasattr(e, 'details') and isinstance(e.details, dict) and e.details.get('u-facingMsg', None)
            else "服务器错误"
        )
        raise InternalServerError({"u-facingMsg": user_facing_msg}) from e
